package com.gym.code.config.admin.service.generate.impl;

import com.gym.code.config.admin.bean.ColumnMappingBean;
import com.gym.code.config.admin.bean.db.DBBaseMappingInfo;
import com.gym.code.config.admin.bean.method.MethodColumnMappingBean;
import com.gym.code.config.admin.bean.method.MethodMappingBean;
import com.gym.code.config.admin.bean.table.TableMappingBean;
import com.gym.code.generator.EnumContants.FieldClassType;
import com.gym.code.generator.EnumContants.MethodOperateType;
import com.gym.code.generator.model.mapping.BaseGenerateModel;
import com.gym.code.generator.model.mapping.ModuleGenerateModel;
import com.gym.code.generator.model.mapping.bean.BeanGenerateModel;
import com.gym.code.generator.model.mapping.bean.EnumGenerateModel;
import com.gym.code.generator.model.mapping.bean.EnumGenerateModel.EnumMappingItem;
import com.gym.code.generator.model.mapping.field.EnumFieldGenerateModel;
import com.gym.code.generator.model.mapping.field.FieldGenerateModel;
import com.gym.code.generator.model.mapping.field.ParameterFieldGenerateModel;
import com.gym.code.generator.model.mapping.field.ParameterListValueFieldGenerateModel;
import com.gym.code.generator.model.mapping.field.ParameterRangeFieldGenerateModel;
import com.gym.code.generator.model.mapping.layer.dao.DaoLayerGenerateModel;
import com.gym.code.generator.model.mapping.layer.dao.IDaoLayerGenerateModel;
import com.gym.code.generator.model.mapping.layer.service.IServiceLayerGenerateModel;
import com.gym.code.generator.model.mapping.layer.service.ServiceLayerGenerateModel;
import com.gym.code.generator.model.mapping.method.AbstractMethodGenerateModel;
import com.gym.code.generator.model.mapping.method.MethodDeleteModel;
import com.gym.code.generator.model.mapping.method.MethodInsertModel;
import com.gym.code.generator.model.mapping.method.MethodSelectModel;
import com.gym.code.generator.model.mapping.method.MethodUpdateModel;

/**
 * 
 * @author xinchun.wang 
   @email: 532002108@qq.com
 * @createTime 2015-5-1 下午12:53:01
 */
public abstract class BeanModelConvertUtils {
	
   public static ModuleGenerateModel convert(DBBaseMappingInfo dbBean ,TableMappingBean tableBean ){
	   ModuleGenerateModel model = new ModuleGenerateModel();
	   BeanGenerateModel beanGenerateModel = wrapBeanGenerateModel(dbBean,tableBean);
	   IDaoLayerGenerateModel daoFaceModel = wrapIDaoLayerGenerateModel(dbBean,tableBean,beanGenerateModel);
	   DaoLayerGenerateModel daoLayerGenerateModel = wrapDaoLayerGenerateModel(dbBean,tableBean,beanGenerateModel);
	   
	   model.setBeanGenerateModel(beanGenerateModel);
	   
	   model.setDaofaceModel(daoFaceModel);
	   model.setDaoLayerGenerateModel(daoLayerGenerateModel);
	   
	   model.setServiceFaceModel(wrapIServiceLayerGenerateModel(dbBean,tableBean,beanGenerateModel));
	   model.setServiceLayerGenerateModel(wrapServiceLayerGenerateModel(dbBean,tableBean,beanGenerateModel));
	   return model;
   }
   
   private static IServiceLayerGenerateModel wrapIServiceLayerGenerateModel(DBBaseMappingInfo dbBean ,TableMappingBean tableBean,BeanGenerateModel beanGenerateModel ){
	   IServiceLayerGenerateModel model = new IServiceLayerGenerateModel();
	   model.setBeanGenerateModel(beanGenerateModel);
	   wrapBaseInfo(model,dbBean);
	   model.setServiceInterfaceName("I"+tableBean.getServiceName());
	   for (MethodMappingBean methodBean : tableBean.getMethodList()) {
		   AbstractMethodGenerateModel methodModel = wrapMethodGenerateModel(methodBean,beanGenerateModel);
		   model.getMethodModelList().add(methodModel);
	   }
	   return model;
   
   }
   
   private static ServiceLayerGenerateModel wrapServiceLayerGenerateModel(DBBaseMappingInfo dbBean ,TableMappingBean tableBean,BeanGenerateModel beanGenerateModel ){
	   ServiceLayerGenerateModel model = new ServiceLayerGenerateModel();
	   model.setBeanGenerateModel(beanGenerateModel);
	   wrapBaseInfo(model,dbBean);
	   model.setDaoClassName(tableBean.getDaoName());
	   model.setDaoFaceName("I" + tableBean.getDaoName());
	   model.setServiceName(tableBean.getServiceName());
	   model.setServiceInterfaceName("I" + tableBean.getServiceName());
	   for (MethodMappingBean methodBean : tableBean.getMethodList()) {
		   AbstractMethodGenerateModel methodModel = wrapMethodGenerateModel(methodBean,beanGenerateModel);
		   model.getMethodModelList().add(methodModel);
	   }
	   return model;
   }
   
   private static BeanGenerateModel wrapBeanGenerateModel(DBBaseMappingInfo dbBean ,TableMappingBean tableBean ) {
	   BeanGenerateModel model = new BeanGenerateModel();
	   wrapBaseInfo(model,dbBean);
	   model.setBeanName(tableBean.getBeanName());
	   model.setTableName(tableBean.getTableName());
	   
	   for( ColumnMappingBean item : tableBean.getColumnList()) {
		   FieldGenerateModel fieldModel = wrapFieldModel(item,model);
		   model.getColumnProperyMappingList().add(fieldModel);
	   }
	   
	   return model;
   }
   
   private static FieldGenerateModel wrapFieldModel(ColumnMappingBean item, BeanGenerateModel model) {
	   FieldGenerateModel fieldModel = null;
	   if(item.isEnum()){
		   EnumFieldGenerateModel enumFieldModel  = new EnumFieldGenerateModel();
		   EnumGenerateModel enumGenerateModel = wrapEnumGenerateModel(item,model);
		   enumFieldModel.setEnumGenerateModel(enumGenerateModel);
		   enumFieldModel.setValueType(FieldClassType.instance(enumGenerateModel.getEnumTypeName()));
		   wrapBaseInfo(enumGenerateModel,model);
		   fieldModel= enumFieldModel;
	   } else {
		   fieldModel = new FieldGenerateModel();
		   fieldModel.setValueType(item.getValueType());
	   }
	   fieldModel.setColumnName(item.getColumnName());
	   fieldModel.setPropertyName(item.getPropertyName());
	   fieldModel.setDesc(item.getDesc());
	   fieldModel.setDefaultValue(item.getDefaultValue());
	   fieldModel.setNullAble(item.isNullAble());
	   fieldModel.setDefaultValue(item.getDefaultValue());
	   return fieldModel;
   }
   
   
   private static EnumGenerateModel wrapEnumGenerateModel(ColumnMappingBean item,BeanGenerateModel beanGenerateModel){
	   EnumGenerateModel model = new EnumGenerateModel();
	   model.setEnumTypeName(item.getEnumTypeName());
	   item.setValueType(item.getEnumTypeName());
	   model.setScope(item.getScope());
	   String patternValue = item.getPatternValue();
	   String[] patternArr = patternValue.split("#");
	   for(String pattern : patternArr) {
		   String[] enumDataArr = pattern.split(",");
		   EnumMappingItem enumItem = new EnumMappingItem(Integer.parseInt(enumDataArr[0]),enumDataArr[1],enumDataArr[2]);
		   model.getEnumMapping().getEnumList().add(enumItem);
	   }
	   wrapBaseInfo(model,beanGenerateModel);
	   return model;
   }
   
   
   private static IDaoLayerGenerateModel wrapIDaoLayerGenerateModel(DBBaseMappingInfo dbBean ,TableMappingBean tableBean,BeanGenerateModel beanGenerateModel ){
	   IDaoLayerGenerateModel model = new IDaoLayerGenerateModel();
	   model.setBeanGenerateModel(beanGenerateModel);
	   wrapBaseInfo(model,dbBean);
	   model.setDaoInterfaceName("I"+tableBean.getDaoName());
	   for (MethodMappingBean methodBean : tableBean.getMethodList()) {
		   AbstractMethodGenerateModel methodModel = wrapMethodGenerateModel(methodBean,beanGenerateModel);
		   model.getMethodModelList().add(methodModel);
	   }
	   return model;
   }
   
   
   private static DaoLayerGenerateModel wrapDaoLayerGenerateModel(DBBaseMappingInfo dbBean ,TableMappingBean tableBean ,BeanGenerateModel beanGenerateModel) {
	   DaoLayerGenerateModel model = new DaoLayerGenerateModel();
	   model.setBeanGenerateModel(beanGenerateModel);
	   wrapBaseInfo(model,dbBean);
	   model.setDaoName(tableBean.getDaoName());
	   model.setTableName(tableBean.getTableName());
	   model.setJdbcTemplateName(dbBean.getJdbcTemplateName());
	   for (MethodMappingBean methodBean : tableBean.getMethodList()) {
		   AbstractMethodGenerateModel methodModel = wrapMethodGenerateModel(methodBean,beanGenerateModel);
		   model.getMethodModelList().add(methodModel);
	   }
	   return model;
   }
   
   
   private static  AbstractMethodGenerateModel wrapMethodGenerateModel(MethodMappingBean methodBean,BeanGenerateModel beanGenerateModel){
	   AbstractMethodGenerateModel model = null;
	   if(methodBean.getMethodOperateType() == MethodOperateType.delete){
		   model = new MethodDeleteModel();
	   } else if(methodBean.getMethodOperateType() == MethodOperateType.insert){
		   model = new MethodInsertModel();
	   } else if(methodBean.getMethodOperateType() == MethodOperateType.update){
		   MethodUpdateModel updateModel = new MethodUpdateModel();
		   for ( MethodColumnMappingBean item : methodBean.getUpdateList()) {
			   ParameterFieldGenerateModel resultFieldModel= wrapParameterFieldGenerateModel(item,beanGenerateModel);
			   updateModel.getUpdateFieldList().add(resultFieldModel);
		   }
		   model = updateModel;
	   } else if(methodBean.getMethodOperateType() == MethodOperateType.select){
		   MethodSelectModel selectModel = new MethodSelectModel();
		   selectModel.setMethodResultType(methodBean.getMethodResultType());
		   for ( MethodColumnMappingBean item : methodBean.getResultList()) {
			   FieldGenerateModel resultFieldModel= wrapResultFieldGenerateModel(item);
			   selectModel.getQueryResultList().add(resultFieldModel);
		   }
		   model = selectModel;
	   }
	   model.setMethodName(methodBean.getFunctionName());
	   model.setMethodParameterType(methodBean.getMethodParameterType());
	   model.setBeanGenerateModel(beanGenerateModel);
	   for(MethodColumnMappingBean item : methodBean.getParameterList()){
		   ParameterFieldGenerateModel parameterModel = wrapParameterFieldGenerateModel(item,beanGenerateModel);
		   model.getParameterList().add(parameterModel);
	   }
	   return model;
   }
   
   
   
   private static ParameterFieldGenerateModel wrapParameterFieldGenerateModel(MethodColumnMappingBean item,BeanGenerateModel beanGenerateModel){
	   ParameterFieldGenerateModel model = null;
	   if(item.isList() ){
		   model = new ParameterListValueFieldGenerateModel();
		   model.setPropertyName((item.getColumnMappingBean().getPropertyName().endsWith("List") || item.getColumnMappingBean().getPropertyName().endsWith("list")) ? item.getColumnMappingBean().getPropertyName():item.getColumnMappingBean().getPropertyName()+"List");
	   } else if(item.isBetween()){
		   ParameterRangeFieldGenerateModel  rangeModel = new ParameterRangeFieldGenerateModel();
		   rangeModel.setPropertyName(item.getColumnMappingBean().getPropertyName());
		   rangeModel.setBeginName(item.getBeginParameterName());
		   rangeModel.setEndName(item.getEndParameterName());
		   model = rangeModel;
	   } else {
		   model = new ParameterFieldGenerateModel();
		   model.setPropertyName(item.getColumnMappingBean().getPropertyName());
	   }
	   //TODO
	   if(item.getColumnMappingBean().isEnum()){
		   EnumGenerateModel enumGenerateModel = wrapEnumGenerateModel(item.getColumnMappingBean(),beanGenerateModel);
		   model.setEnumGenerateModel(enumGenerateModel);
	   }
	   model.setColumnName(item.getColumnMappingBean().getColumnName());
	   model.setDefaultValue(item.getColumnMappingBean().getDefaultValue());
	   model.setPropertyName(item.getColumnMappingBean().getPropertyName());
	   model.setValueType(item.getColumnMappingBean().getValueType());
	   return model;
   }
   
   private static FieldGenerateModel wrapResultFieldGenerateModel(MethodColumnMappingBean item){
	   FieldGenerateModel model = new FieldGenerateModel();
	   model.setColumnName(item.getColumnMappingBean().getColumnName());
	   model.setDefaultValue(item.getColumnMappingBean().getDefaultValue());
	   model.setPropertyName(item.getColumnMappingBean().getPropertyName());
	   model.setValueType(item.getColumnMappingBean().getValueType());
	   return model;
   }
   
   private static <T extends BaseGenerateModel> T wrapBaseInfo(T model,DBBaseMappingInfo baseGenerateModel){
	   model.setBasePath(baseGenerateModel.getBasePath());
	   model.setPackagePath(baseGenerateModel.getPackagePath());
	   model.setCreater(baseGenerateModel.getCreater());
	   return model;
   }
   
   
   private static <T extends BaseGenerateModel> T wrapBaseInfo(T model,BeanGenerateModel baseGenerateModel){
	   model.setBasePath(baseGenerateModel.getBasePath());
	   model.setPackagePath(baseGenerateModel.getPackagePath());
	   model.setCreater(baseGenerateModel.getCreater());
	   return model;
   }
   
}
